﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;

namespace Moonwish.Silverlight.Core
{
    /// <summary>
    /// 事件转命令触发器，write by zhlin 2011-02-28
    /// </summary>
    public class EventToCommandTrigger : TriggerAction<DependencyObject>
    {
        /// <summary>
        /// 是否忽略事件的参数。
        /// </summary>
        public bool PassEventArgsToCommand
        {
            get;
            set;
        }

        /// <summary>
        /// 用于绑定的Command属性。
        /// </summary>
        public ICommand Command
        {
            get
            {
                return (ICommand)GetValue(CommandProperty);
            }

            set
            {
                SetValue(CommandProperty, value);
            }
        }

        /// <summary>
        /// 用于绑定的Command属性的静态依赖属性。
        /// </summary>
        public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
            "Command",
            typeof (ICommand),
            typeof (EventToCommandTrigger),
            new PropertyMetadata(
                null,
                (s, e) => OnCommandChanged(s as EventToCommandTrigger, e)));

        /// <summary>
        /// Command属性改变事件。
        /// </summary>
        /// <param name="element"></param>
        /// <param name="e"></param>
        private static void OnCommandChanged(EventToCommandTrigger element, DependencyPropertyChangedEventArgs e)
        {
            if (element == null)
            {
                return;
            }

            if (e.OldValue != null)
            {
                ((ICommand)e.OldValue).CanExecuteChanged -= element.OnCommandCanExecuteChanged;
            }

            var command = (ICommand)e.NewValue;

            if (command != null)
            {
                command.CanExecuteChanged += element.OnCommandCanExecuteChanged;
            }

            element.EnableDisableElement();
        }

        /// <summary>
        /// 当命令属性改变时，检查是否能被执行。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnCommandCanExecuteChanged(object sender, EventArgs e)
        {
            EnableDisableElement();
        }

        /// <summary>
        /// 检查Command是否能在附加对象上执行。
        /// </summary>
        private void EnableDisableElement()
        {
            var control = AssociatedObject as Control;

            if (control == null)
            {
                return;
            }

            if (Command != null)
            {
                control.IsEnabled = Command.CanExecute(CommandParameterValue);
            }
        }

        private object _commandParameterValue;
        /// <summary>
        /// 命令参数值。
        /// </summary>
        public object CommandParameterValue
        {
            get
            {
                return _commandParameterValue ?? CommandParameter;
            }

            set
            {
                _commandParameterValue = value;
                EnableDisableElement();
            }
        }

        /// <summary>
        /// 命令参数。
        /// </summary>
        public object CommandParameter
        {
            get
            {
                return GetValue(CommandParameterProperty);
            }

            set
            {
                SetValue(CommandParameterProperty, value);
            }
        }
        /// <summary>
        /// 命令参数静态依赖属性。
        /// </summary>
        public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register(
            "CommandParameter",
            typeof(object),
            typeof(EventToCommandTrigger),
            new PropertyMetadata(
                null,
                (s, e) =>
                {
                    var sender = s as EventToCommandTrigger;
                    if (sender == null)
                    {
                        return;
                    }

                    if (sender.AssociatedObject == null)
                    {
                        return;
                    }

                    sender.EnableDisableElement();
                }));

        /// <summary>
        /// 重写触发器调用方法。
        /// </summary>
        /// <param name="parameter"></param>
        protected override void Invoke(object parameter)
        {
            var element = (FrameworkElement)AssociatedObject;

            if (element == null)
            {
                return;
            }

            var command = Command;
            var commandParameter = CommandParameterValue;

            if (commandParameter == null
                && PassEventArgsToCommand)
            {
                commandParameter = parameter;
            }

            if (command != null
                && command.CanExecute(commandParameter))
            {
                command.Execute(commandParameter);
            }
        }
    }
}
